import undici, { Dispatcher } from 'undici';
import { API } from '../config/config';
import api from './api';
type Response = { status: number; data: any; };
type Options = Dispatcher.DispatchOptions;
type Interceptor = (options: Options, next: (options: Options) => Promise<Response>) => Promise<Response>;
let _interceptor: Interceptor;


const IS_DEBUG = process.env.NODE_ENV == 'development';

const http = {
    setInterceptor(interceptor: Interceptor) {
        _interceptor = interceptor;
    },
    request(opts: { path: string, method: Dispatcher.HttpMethod }) {
        return (data?: any): Promise<Response> => {
            let options: Options = {
                path: opts.path,
                method: opts.method
            };

            if (opts.method == 'GET') {
                options.query = data;
            } else {
                options.body = data;
            }


            const next = async (options: Options) => {
                const res = await undici.request(API, options);
                const body = await res.body.text();

                try {
                    const data = JSON.parse(api.rsaDecrypt(body));
                    if (IS_DEBUG) {
                        console.log({
                            status: res.statusCode,
                            data
                        });
                    }
                    return {
                        status: res.statusCode,
                        data
                    };
                } catch (error) {
                    try {
                        const data = JSON.parse(body);
                        if (IS_DEBUG) {
                            console.log({
                                status: res.statusCode,
                                data
                            });
                        }
                        return {
                            status: res.statusCode,
                            data
                        };
                    } catch (error) {
                        console.log({
                            path: opts.path,
                            status: res.statusCode,
                            body
                        });
                        throw error;

                    }

                }

            }
            if (_interceptor) {
                return _interceptor(options, next);
            } else {
                return next(options);
            }
        }
    },

    get(path: string) {
        return http.request({ path, method: "GET" });
    },

    post(path: string) {
        return http.request({ path, method: "POST" });
    },

    put(path: string) {
        return http.request({ path, method: "PUT" });
    },

    delete(path: string) {
        return http.request({ path, method: "DELETE" });
    },
};


export default http;